#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <pthread.h>

#define TAMM 1000

using namespace std;

double **matr;

double z;

void* calculo(void *a);

int menu();

void llenarM(string c, int &a, int &b);

int main(int argc, char ** argv){

  double C,h,dt;//Constantes del sistema.

  string cad;//nombre de archivo de entrada.

  int opc;

  int tamb;//Tamaño de la barra

  int tamt;//Cantidad de muestras de temperatura.

  int var[3];//parametros de los hilos

  int nh;//numeros de hilos
  
  pthread_t *hilos;//Coleccion de hilos

  ofstream salida("salida.txt");//archivo de salida

  void *aux;//puntero auxiliar. sin uso.
  
  if(argc==1){
    do{

      opc=menu();
      
      switch(opc){
	case 1:
	  cout<<"ingrece nombre del archivo de entrada: ";
	  cin>>cad;
	  llenarM(cad, tamt, tamb);
	  cout<<"ingrece valor de C: ";
	  cin>>C;
	  cout<<"ingrece el valor de paso (h): ";
	  cin>>h;
	  cout<<"ingrece el delta t: ";
	  cin>>dt;
	  break;
	case 2:
		//ingreso de datos manualmente
	  break;
	case 3:
	  cout<<"adios"<<endl;
	default:
	  cout<<"opcion incorrecta"<<endl;
      }
    }while(opc>3 || opc<1);
  }
  else
    if(argc==5){//Ingreso por paramentos via consola.
      cad=argv[1];
      C=atof(argv[2]);
      h=atof(argv[3]);
      dt=atof(argv[4]);
      llenarM(cad,tamt,tamb);
    }
    else{
      cout<<"Error: parametros incorrecto"<<endl;
      return 1;
    }
  
  z = C*dt/(h*h);
  if(z>0.50)
	cout<<"Poble error: z > 0.50"<<endl;

  nh = tamb/3;
  hilos= new pthread_t[nh];

  var[0] = 1;
  var[1] = 3;
  var[2] = tamt;

  for(int i=0; i < nh ; i++){//
	pthread_create(&hilos[i],NULL,calculo,(void *)var);
	var[0]+=3;
	if((var[1]+5)>=tamb)
		var[1]=tamb-2;
	else
		var[1]+=3;

  }

  for(int i=0;i<nh;i++)//esperar a que los hilos terminen.
	pthread_join(hilos[i], &aux);
	
  for(int i=0;i<tamt-1;i++){
    for(int j=1;j<tamb-1;j++){
	salida<<matr[i][j]<<" ";
    }
    salida<<endl;
  }

  salida.close();
  return 0;
}



void llenarM(string c, int &a, int &b){
  double aux[TAMM][TAMM]={0};
  int i=0,i1=0,j=0,j1=1;
  ifstream entrada(c.c_str());

  getline(entrada, c);
  do{
    i=c.find(' ',i1);
    if(i==string::npos)
      i=c.length();
    aux[0][j]=atof((c.substr(i1,i-i1)).c_str());
    j++;
    i1=i+1;
  }while(i!=c.length());
  b=j;
  j=1;
  i1=0;

  getline(entrada, c);
  do{
    i=c.find(' ',i1);
    if(i==string::npos)
      i=c.length();
    aux[j][0]=atof((c.substr(i1,i-i1)).c_str());
    j++;
    i1=i+1;
  }while(i!=c.length());
  i1=0;
  
  getline(entrada, c);
  do{
    i=c.find(' ',i1);
    if(i==string::npos)
      i=c.length();
    aux[j1][b-1]=atof((c.substr(i1,i-i1)).c_str());
    j1++;
    i1=i+1;
  }while(i!=c.length());

  if(j!=j1)
    a=0;
  else{
    a=j;
    matr= new double *[a];
    for(i=0; i<a; i++){
      matr[i]=new double[b];
      matr[i][0]=aux[i][0];
      matr[i][b-1]=aux[i][b-1];
      if(i==0)
      	for(j=1;j<b-1;j++)
	  matr[i][j]=aux[i][j];
    }
  }
  entrada.close();
}


int menu(){
  return 1;
}


void* calculo(void *a){
	int *b =(int*) a;

	for(int i=0; i < b[2]-1; i++){
		matr[i+1][b[0]]=z*matr[i][b[0]-1]+(1-2*z)*matr[i][b[0]]+z*matr[i][b[0]+1];
		matr[i+1][b[1]]=z*matr[i][b[1]-1]+(1-2*z)*matr[i][b[1]]+z*matr[i][b[1]+1];
		for(int j=b[0]+1; j <= b[1]-1 ; j++)
			matr[i+1][j]=z*matr[i][j-1]+(1-2*z)*matr[i][j]+z*matr[i][j+1];
		
	}

	pthread_exit(NULL);
}
